package com.controller;


import com.dto.BaseDto;
import com.utils.ContextUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.Optional;

@Controller
@RequestMapping(value = "/page")//restController 将controller的mapping 和方法的mapping结合作为访问路径
public class UrlController {
    //花括号中的变量和方法中的参数对应绑定传参数
    //例如 /arrive/student/add
    @Resource
    HttpServletRequest request;

    @RequestMapping(value = "/arrive/{option}/{subject}/{pagename}")
    public ModelAndView arriveUrl
            (@PathVariable("option") String option, @PathVariable("subject") String subject, @PathVariable("pagename") String pagename) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
        ModelAndView mv = new ModelAndView("/" + option + "/" + subject + "/" + pagename);
        addOtherDto(mv, request);
        return mv;
    }

    @RequestMapping(value = "/arrive/{option}/{pagename}")
    public ModelAndView arriveUrlShort
            (@PathVariable("option") String option, @PathVariable("pagename") String pagename) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        ModelAndView mv = new ModelAndView("/" + option + "/" + pagename);
        addOtherDto(mv, request);
        return mv;
    }


    public void addOtherDto(ModelAndView mv, HttpServletRequest request) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Optional<String> serviceName = Optional.ofNullable(request.getParameter("service"));
        Optional<String> methodName = Optional.ofNullable(request.getParameter("method"));
        Optional<String> paramsStr = Optional.ofNullable(request.getParameter("paramValStr"));
        String[] paramsValueStr = null;
        Object[] params = null;
        Class[] paramClazz = null;
        //利用传过来的service名字 和 方法名字   利用java反射进行调用
        if (serviceName.isPresent() && methodName.isPresent()) {
            Object obj = ContextUtils.getSpringMVCContext().getBean(serviceName.get() + "Service");
            Class clazz = obj.getClass();
//根据传递过来的参数数量决定参数个数
            int paramCount =
                    Integer.parseInt(Optional.ofNullable(request.getParameter("paramNo")).orElse("0"));//如果没有参数 默认值 参数数量为0
            String paramValStr = request.getParameter("paramValStr");
            String paramClazzStr = request.getParameter("paramClazzStr");

            String[] paramValues = paramValStr.split(",");

            String[] paramClazzStrs = paramClazzStr.split(",");

            if (paramCount > 0) {//如果本次方法需要参数
                paramClazz = new Class[paramCount];
                params = new Object[paramCount];
                for (int i = 0; i < paramCount; i++) {
                    //System.out.println(paramClazzStrs[i]);
                    paramClazz[i] = getClazz(paramClazzStrs[i]);
                    params[i] = getValue(paramValues[i]);
                    //System.out.println(paramClazz[i].getName());
                }
            }
//参考url  http://localhost:8081/page/arrive/back/goods/add?service=admin&method=test&paramNo=2&paramClazzStr=1,2&paramValStr=1,aaa
            Method method = clazz.getDeclaredMethod(methodName.get(),paramClazz);
            BaseDto dto = null;
            dto = (BaseDto) method.invoke(obj, params);
            mv.addObject("otherDto", dto);//保存到request
        }
    }

    @RequestMapping("home")
    public String index() {
        return "index";
    }

    public Class getClazz(String clazzNo) {
        Class clazz = null;
        switch (clazzNo) {
            case "1":
                clazz = Integer.class;
                break;
            case "2":
                clazz = String.class;
                break;
            case "3":
                clazz = Float.class;
                break;
            case "4":
                clazz = Double.class;
                break;
            case "5":
                clazz = Date.class;
                break;
            default:
                clazz = Integer.class;
                break;
        }
        return clazz;
    }

    public Object getValue(String valueStr) {
        Object obj = null;
        switch (valueStr) {
            case "1":
                obj = Integer.parseInt(valueStr);
                break;
            case "2":
                obj = valueStr;
                break;
            case "3":
                obj = Float.parseFloat(valueStr);
                break;
            case "4":
                obj = Double.parseDouble(valueStr);
                break;
            case "5":
                obj = Date.parse(valueStr);
                break;
            default:
                obj = valueStr;
                break;
        }
        return obj;
    }



}
